//
//  JCChatRoomChatViewController.swift
//  JChat
//
//  Created by xudong.rao on 2019/4/17.
//  Copyright © 2019 HXHG. All rights reserved.
//

import UIKit
import MTCategory
import YHPhotoKit
import MobileCoreServices
import MTCategory
import YPNavigationBarTransition
import RxSwift
import RxCocoa

class JCChatRoomChatViewController: BaseViewController {

    private lazy var provider: MTProvider<MTDiscoverAPI> = {
        let provider = MTProvider<MTDiscoverAPI>(plugins: [MTLoadingDataPlugin.init(viewController: self)])
        return provider
    }()
    
    public var conversation: JMSGConversation
    public var chatRoom: JMSGChatRoom
    //MARK - life cycle
    public required init(conversation: JMSGConversation,room: JMSGChatRoom) {
        self.conversation = conversation
        self.chatRoom = room;
        super.init()
        automaticallyAdjustsScrollViewInsets = false;
        JMessage.add(self, with: self.conversation)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    required public init(rounterParams params: Dictionary<String, Any>?) {
        fatalError("init(rounterParams:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.theme.background
        if #available(iOS 10.0, *) {
            navigationController?.tabBarItem.badgeColor = UIColor(hex: 0xEB424C)
        }
        NotificationCenter.default.addObserver(self, selector: #selector(_updateFileMessage(_:)), name: NSNotification.Name(rawValue: kUpdateFileMessage), object: nil)

        _init()
        
        self.title = "广场"
        
        let ruleButton = UIButton(type: .custom)
        ruleButton.setTitle("规则", for: .normal)
        ruleButton.titleLabel?.font = PingFangSCRegularFont(14)
        ruleButton.setTitleColor(UIColor.text.x1d1a1a, for: .normal)
        ruleButton.addTarget(self, action: #selector(JCChatRoomChatViewController.rule), for: .touchUpInside)
        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: ruleButton)
        loadRankingChampion()
    }
    
    private func loadRankingChampion() {
        MTDiscoverTool.rankingCahmpion(provider: provider, complete: {[weak self] (model) in
            guard let weakSelf = self else { return }
            if model?.code == 200, model?.result?.count ?? 0 > 0 {
                weakSelf.noticeView.isHidden = false
                weakSelf.noticeView.model = model
                weakSelf.noticeView.snp.updateConstraints { (make) in
                    make.height.equalTo(32)
                }
            } else {
                weakSelf.noticeView.isHidden = true
                weakSelf.noticeView.snp.updateConstraints { (make) in
                    make.height.equalTo(0)
                }
            }
        }) { (error) in
            
        }
    }
    
    @objc private func rule() {
        ruleView.isHidden = false
    }
    
    lazy var ruleView: JCChatRoomRuleView = {
        let v = JCChatRoomRuleView()
        v.frame = self.view.bounds
        v.isHidden = true
        return v
    }()
    
    @objc func _updateFileMessage(_ notification: Notification) {
        let userInfo = notification.userInfo
        let message = userInfo?[kUpdateFileMessage] as! JMSGMessage
        let content = message.content as! JMSGFileContent
        let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
        let data = try! Data(contentsOf: url)
        updateMediaMessage(message, data: data)
    }

    override func loadView() {
        super.loadView()
        let frame = CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height)
        chatView = JCChatView(frame: frame, chatViewLayout: chatViewLayout)
        chatView.delegate = self
        chatView.messageDelegate = self
        chatView.cancelHeaderPull()
        toolbar.translatesAutoresizingMaskIntoConstraints = false
        toolbar.delegate = self
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        toolbar.isHidden = false
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameChanged(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
        if let group = conversation.target as? JMSGGroup {
            self.title = group.displayName()
        }
        navigationController?.interactivePopGestureRecognizer?.delegate = self
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        navigationController?.navigationBar.isTranslucent = true
        JCDraft.update(text: toolbar.text, conversation: conversation)
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
        JMessage.remove(self, with: conversation)
    }
    
    fileprivate lazy var toolbar: SAIInputBar = SAIInputBar(type: .default)
    fileprivate lazy var inputViews: [String: UIView] = [:]
    fileprivate weak var inputItem: SAIInputItem?
    var chatViewLayout: JCChatViewLayout = .init()
    var chatView: JCChatView!
    fileprivate lazy var documentInteractionController = UIDocumentInteractionController()
    
    
    lazy var noticeView: MTChatRoomTopRateView = {
        let v = MTChatRoomTopRateView()
        return v
    }()
    
    fileprivate lazy var imagePicker: UIImagePickerController = {
        var picker = UIImagePickerController()
        picker.modalPresentationStyle = .fullScreen
        picker.sourceType = .camera
        picker.cameraCaptureMode = .photo
        picker.delegate = self
        return picker
    }()
    
    fileprivate lazy var videoPicker: UIImagePickerController = {
        var picker = UIImagePickerController()
        picker.modalPresentationStyle = .fullScreen
        picker.mediaTypes = [kUTTypeMovie as String]
        picker.sourceType = .camera
        picker.cameraCaptureMode = .video
        picker.videoMaximumDuration = 10
        picker.delegate = self
        return picker
    }()
    
    fileprivate lazy var _emoticonGroups: [JCCEmoticonGroup] = {
        var groups: [JCCEmoticonGroup] = []
        if let group = JCCEmoticonGroup(identifier: "com.apple.emoji") {
            groups.append(group)
        }
        if let group = JCCEmoticonGroup(identifier: "cn.jchat.guangguang") {
            groups.append(group)
        }
        return groups
    }()
    fileprivate lazy var _emoticonSendBtn: UIButton = {
        var button = UIButton()
        button.titleLabel?.font = UIFont.systemFont(ofSize: 15)
        button.contentEdgeInsets = UIEdgeInsets.init(top: 0, left: 10 + 8, bottom: 0, right: 8)
        button.setTitle("发送", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.setBackgroundImage(UIImage(color: UIColor.theme.main, size: CGSize(width: 60, height: 40)), for: .normal)
        button.setBackgroundImage(UIImage(color: .white, size: CGSize(width: 60, height: 40)), for: .disabled)
        button.addTarget(self, action: #selector(_sendHandler), for: .touchUpInside)
        return button
    }()
    fileprivate lazy var emoticonView: JCEmoticonInputView = {
        let emoticonView = JCEmoticonInputView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 275))
        emoticonView.delegate = self
        emoticonView.dataSource = self
        return emoticonView
    }()
    
    fileprivate lazy var toolboxView: SAIToolboxInputView = {
        var toolboxView = SAIToolboxInputView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 138))
        toolboxView.delegate = self
        toolboxView.dataSource = self
        return toolboxView
    }()
    // MARK: 工具条数据源
    fileprivate lazy var _toolboxItems: [SAIToolboxItem] = {
        if UserDefaults.AppValidate.isValidate.storedBool {
            return [
                        SAIToolboxItem("page:pic", "照片", UIImage.loadImage("chat_tool_pic")),
                        SAIToolboxItem("page:camera", "拍照", UIImage.loadImage("chat_tool_camera"))
                    ]
        }
        return [
            SAIToolboxItem("page:pic", "照片", UIImage.loadImage("chat_tool_pic")),
            SAIToolboxItem("page:camera", "拍照", UIImage.loadImage("chat_tool_camera")),
            SAIToolboxItem("page:redpack", "红包", UIImage.loadImage("icon_packet"))
//            ,
//            SAIToolboxItem("page:location", "位置", UIImage.loadImage("chat_tool_location")),
//            SAIToolboxItem("page:businessCard", "名片", UIImage.loadImage("chat_tool_businessCard")),
        ]
    }()
    
    fileprivate var myAvator: UIImage?
    lazy var messages: [JCMessage] = []
    lazy var jmessages: [JMSGMessage] = []
    fileprivate let currentUser = JMSGUser.myInfo()
    fileprivate var messagePage = 0
    fileprivate var currentMessage: JCMessageType!
    fileprivate var maxTime = 0
    fileprivate var minTime = 0
    fileprivate var minIndex = 0
    fileprivate var jMessageCount = 0
    fileprivate var isFristLaunch = true
    fileprivate var recordingHub: JCRecordingView!
    fileprivate var needLastJMSGMessage: JMSGMessage?
    fileprivate lazy var recordHelper: JCRecordVoiceHelper = {
        let recordHelper = JCRecordVoiceHelper()
        recordHelper.delegate = self
        return recordHelper
    }()
    
    private func _init() {
        view.backgroundColor = .white
        self.title = self.chatRoom.displayName()
        myAvator = UIImage.getMyAvator()
        _setupNavigation()

        let tap = UITapGestureRecognizer(target: self, action: #selector(_tapView))
        tap.delegate = self
        chatView.addGestureRecognizer(tap)
        view.addSubview(noticeView)
        view.addSubview(chatView)
        
        noticeView.snp.makeConstraints { (make) in
            make.top.equalToSuperview().offset(NavigationBarHeight + StatusBarHeight)
            make.left.right.equalToSuperview()
            make.height.equalTo(32)
        }
        
        chatView.snp.makeConstraints { (make) in
            //make.edges.equalToSuperview()
            make.top.equalTo(noticeView.snp.bottom)
            make.left.right.bottom.equalToSuperview()
        }
        
        UIApplication.mt_keyWindow?.addSubview(ruleView)
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameChanged(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }
    /// 点击界面
    @objc func _tapView() {
        view.endEditing(true)
        toolbar.resignFirstResponder()
    }
    
    /// 键盘监听
    @objc func keyboardFrameChanged(_ notification: Notification) {
        let dic = NSDictionary(dictionary: (notification as NSNotification).userInfo!)
        let keyboardValue = dic.object(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue
        let bottomDistance = UIScreen.main.bounds.size.height - keyboardValue.cgRectValue.origin.y
        let duration = Double(truncating: dic.object(forKey: UIResponder.keyboardAnimationDurationUserInfoKey) as! NSNumber)
        
        UIView.animate(withDuration: duration, animations: {
        }) { (finish) in
            if (bottomDistance == 0 || bottomDistance == self.toolbar.height) && !self.isFristLaunch {
                return
            }
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
                self.chatView.scrollToLast(animated: false)
            }
            self.isFristLaunch = false
        }
    }
    
    /// 设置导航栏按钮
    private func _setupNavigation() {
        
        navigationController?.interactivePopGestureRecognizer?.isEnabled = true
        navigationController?.interactivePopGestureRecognizer?.delegate = self
        
        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: navBackButton)
    }
    
    /// 返回上一层目录
    @objc func _back() {
        JMSGChatRoom.leaveChatRoom(withRoomId: self.chatRoom.roomID) { (result, error) in
            printLog("leave the chat room，error:\(error)")
            self.navigationController?.popViewController(animated: true)
        }
    }
    
    lazy var navBackButton: UIButton = {
        let btn = UIButton(type: .custom)
        btn.setImage(UIImage(named: "nav_back"), for: .normal)
        btn.addTarget(self, action: #selector(_back), for: .touchUpInside)
        return btn
    }()
    
    /// 进入设置界面
    @objc func _getChatRoomInfo() {
        let vc = JCChatRoomInfoTableViewController.init(nibName: "JCChatRoomInfoTableViewController", bundle: nil)
        vc.chatRoom = self.chatRoom
        self.navigationController?.pushViewController(vc, animated: true)
    }
    @objc func _sendHandler() {
        let text = toolbar.attributedText
        if text != nil && (text?.length)! > 0 {
            send(forText: text!)
            toolbar.attributedText = nil
        }
    }
    
    private func isNeedInsertTimeLine(_ time: Int) -> Bool {
        if maxTime == 0 || minTime == 0 {
            maxTime = time
            minTime = time
            return true
        }
        if (time - maxTime) >= 5 * 60000 {
            maxTime = time
            return true
        }
        if (minTime - time) >= 5 * 60000 {
            minTime = time
            return true
        }
        return false
    }
    
    // MARK: - parse message
    fileprivate func _parseMessage(_ message: JMSGMessage, _ isNewMessage: Bool = true) -> JCMessage {
        if isNewMessage {
            jMessageCount += 1
        }
        return message.parseMessage(self, { [weak self] (message, data) in
            self?.updateMediaMessage(message, data: data)
        })
    }
    
    // MARK: - send message
    func send(_ message: JCMessage, _ jmessage: JMSGMessage) {
        printLog("send message: JCMessage,JMSGMessage")
        if isNeedInsertTimeLine(jmessage.timestamp.intValue) {
            let timeContent = JCMessageTimeLineContent(date: Date(timeIntervalSince1970: TimeInterval(jmessage.timestamp.intValue / 1000)))
            let m = JCMessage(content: timeContent)
            m.options.showsTips = false
            messages.append(m)
            chatView.append(m)
        }
        message.msgId = jmessage.msgId
        message.name = currentUser.displayName()
        message.senderAvator = myAvator
        message.sender = currentUser
        message.options.alignment = .right
        message.options.state = .sending
        message.targetType = .chatRoom
        message.contentType = jmessage.contentType
        message.jmessage = jmessage
        chatView.append(message)
        messages.append(message)
        jmessages.append(jmessage)
        chatView.scrollToLast(animated: false)
        conversation.send(jmessage)
    }
    
    ///  发文本
    func send(forText text: NSAttributedString) {
        let message = JCMessage(content: JCMessageTextContent(attributedText: text))
        let content = JMSGTextContent(text: text.string)
        let msg = JMSGMessage.ex.createMessage(conversation, content, nil)
//        reminds.removeAll()
        send(message, msg)
    }
    /// 发表情
    func send(forLargeEmoticon emoticon: JCCEmoticonLarge) {
        guard let image = emoticon.contents as? UIImage else {
            return
        }
        let messageContent = JCMessageImageContent()
        messageContent.image = image
        messageContent.delegate = self
        messageContent.isLargeEmoticon = true
        let message = JCMessage(content: messageContent)
        
        let content = JMSGImageContent(imageData: image.pngData()!)
        let msg = JMSGMessage.ex.createMessage(conversation, content!, nil)
        msg.ex.isLargeEmoticon = true
        message.options.showsTips = true
        send(message, msg)
    }
    /// 发图片
    func send(forImage image: UIImage) {
        let data = image.jpegData(compressionQuality: 1.0)!
        let content = JMSGImageContent(imageData: data)
        
        let message = JMSGMessage.ex.createMessage(conversation, content!, nil)
        let imageContent = JCMessageImageContent()
        imageContent.delegate = self
        imageContent.image = image
        content?.uploadHandler = {  (percent:Float, msgId:(String?)) -> Void in
            imageContent.upload?(percent)
        }
        let msg = JCMessage(content: imageContent)
        send(msg, message)
    }
    /// 发语音
    func send(voiceData: Data, duration: Double) {
        let voiceContent = JCMessageVoiceContent()
        voiceContent.data = voiceData
        voiceContent.duration = duration
        voiceContent.delegate = self
        let content = JMSGVoiceContent(voiceData: voiceData, voiceDuration: NSNumber(value: duration))
        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
        
        let msg = JCMessage(content: voiceContent)
        send(msg, message)
    }
    /// 发视频
    func send(videoData: Data, thumbData: Data, duration: Double,format: String)  {
        let time = NSNumber(value: duration)
        let content = JMSGVideoContent(videoData: videoData, thumbData: thumbData, duration: time)
        content.format = format
        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
        
        let videoContent = JCMessageVideoContent()
        videoContent.videoContent = content
        videoContent.data = videoData
        videoContent.image = UIImage(data: thumbData)
        videoContent.delegate = self
        
        let msg = JCMessage(content: videoContent)
        send(msg, message);
    }
    /// 发文件
    func send(fileData: Data, fileName: String) {
        let videoContent = JCMessageVideoContent()
        videoContent.data = fileData
        videoContent.delegate = self
        
        let content = JMSGFileContent(fileData: fileData, fileName: fileName)
        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
        let msg = JCMessage(content: videoContent)
        send(msg, message)
    }
    /// 发送地理位置
    func send(address: String, lon: NSNumber, lat: NSNumber) {
        let locationContent = JCMessageLocationContent()
        locationContent.address = address
        locationContent.lat = lat.doubleValue
        locationContent.lon = lon.doubleValue
        locationContent.delegate = self
        
        let content = JMSGLocationContent(latitude: lat, longitude: lon, scale: NSNumber(value: 1), address: address)
        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
        let msg = JCMessage(content: locationContent)
        send(msg, message)
    }
    
    /// 发送红包
    func sendRedpack() {
        MTRedpackTool.default.sendRedpack(self, self.conversation) {_ in 
            
        }
    }
    
    //Mark: - 自定义通知栏消息 是否显示 - 显示的内容
    func send(_ message: JCMessage, _ jmessage: JMSGMessage, _ optional: JMSGOptionalContent) {
        let m = bulidMsg(msg:jmessage)
        if needLastJMSGMessage == nil {
            messages.append(m)
            chatView.append(m)
            needLastJMSGMessage = jmessage
        }else {
            if isNeedTimeLine(needLastJMSGMessage!,lastMsg: jmessage) {
                messages.append(m)
                chatView.append(m)
                needLastJMSGMessage = jmessage
            }
        }
        message.msgId = jmessage.msgId
        message.name = currentUser.displayName()
        message.senderAvator = myAvator
        message.sender = currentUser
        message.options.alignment = .right
        message.options.state = .sending
        
        chatView.append(message)
        messages.append(message)
        chatView.scrollToLast(animated: false)
        conversation.send(jmessage, optionalContent:optional)
    }
    
    //Mark: - 构建时间提示信息
    ///
    /// - Parameter msg: 具体消息(JMSGMessage)的所有消息
    /// - Returns: 返回时间消息类型
    func bulidMsg(msg: JMSGMessage) -> JCMessage {
        let timeContent = JCMessageTimeLineContent(date: Date(timeIntervalSince1970: TimeInterval(msg.timestamp.intValue / 1000)))
        let m = JCMessage(content: timeContent)
        return m
    }
    
    /// 计算两条消息之间的时间差, 超过五分钟需要显示时间标签
    ///
    /// - Parameters:
    ///   - currentMsg: 当前消息
    ///   - lastMsg: 上一条消息
    /// - Returns: 是否需要显示时间标签
    func isNeedTimeLine(_ currentMsg: JMSGMessage,lastMsg: JMSGMessage) -> Bool {
        let time: Int = currentMsg.timestamp.intValue
        let time2: Int = lastMsg.timestamp.intValue
        //print_c(message: "time : \(time2) - \(time) = \(time2 - time)")
        if time2 - time >= 1 * 60000 {
            return true
        }
        return false
    }
}

//MARK: - JMSGMessage Delegate
extension JCChatRoomChatViewController: JMessageDelegate {
    fileprivate func updateMediaMessage(_ message: JMSGMessage, data: Data?) {
        DispatchQueue.main.async {
            if let index = self.messages.index(message) {
                let msg = self.messages[index]
                switch(message.contentType) {
                case .file:
                    printLog("update file message")
                    if message.ex.isShortVideo {
                        let videoContent = msg.content as! JCMessageVideoContent
                        videoContent.data = data
                        videoContent.delegate = self
                        msg.content = videoContent
                    } else {
                        let fileContent = msg.content as! JCMessageFileContent
                        fileContent.data = data
                        fileContent.delegate = self
                        msg.content = fileContent
                    }
                case .video:
                    printLog("updare video message")
                    let videoContent = msg.content as! JCMessageVideoContent
                    videoContent.image = UIImage(data: data!)
                    videoContent.delegate = self
                    msg.content = videoContent
                case .image:
                    let imageContent = msg.content as! JCMessageImageContent
                    let image = UIImage(data: data!)
                    imageContent.image = image
                    msg.content = imageContent
                default: break
                }
                msg.updateSizeIfNeeded = true
                self.chatView.update(msg, at: index)
                msg.updateSizeIfNeeded = false
            }
        }
    }
    
    func onReceiveChatRoomConversation(_ conversation: JMSGConversation!, messages: [JMSGMessage]!) {
        printLog("message: \(String(describing: messages))")
        
        for index in 0..<messages.count {
            let msg = messages[index]
            let message = _parseMessage(msg)
            if self.messages.contains(where: { (m) -> Bool in
                return m.msgId == message.msgId
            }) {
                let indexs = chatView.indexPathsForVisibleItems
                for index in indexs {
                    var m = self.messages[index.row]
                    if !m.msgId.isEmpty {
                        if let msg = conversation.message(withMessageId: m.msgId) {
                            m = _parseMessage(msg, false)
                            chatView.update(m, at: index.row)
                        }
                    }
                }
                return
            }
            
            let jmessage = msg
            if isNeedInsertTimeLine(jmessage.timestamp.intValue) {
                let timeContent = JCMessageTimeLineContent(date: Date(timeIntervalSince1970: TimeInterval(jmessage.timestamp.intValue / 1000)))
                let m = JCMessage(content: timeContent)
                m.options.showsTips = false
                self.messages.append(m)
                chatView.append(m)
            }
            self.messages.append(message)
            self.jmessages.append(msg)
            chatView.append(message)
            conversation.clearUnreadCount()
            if !chatView.isRoll {
                chatView.scrollToLast(animated: true)
            }
        }
    }
    
//    func onReceiveChatRoomConversation(_ conversation: JMSGConversation!, messages: [JMSGMessage]!) {
//        printLog("message: \(String(describing: messages))")
//
//        for index in 0..<messages.count {
//            let msg = messages[index]
//            let message = _parseMessage(msg)
//            if self.messages.contains(where: { (m) -> Bool in
//                return m.msgId == message.msgId
//            }) {
//                let indexs = chatView.indexPathsForVisibleItems
//                for index in indexs {
//                    var m = self.messages[index.row]
//                    if !m.msgId.isEmpty {
//                        if let msg = conversation.message(withMessageId: m.msgId) {
//                            m = _parseMessage(msg, false)
//                            chatView.update(m, at: index.row)
//                        }
//                    }
//                }
//                return
//            }
//
//            let jmessage = msg
//            if isNeedInsertTimeLine(jmessage.timestamp.intValue) {
//                let timeContent = JCMessageTimeLineContent(date: Date(timeIntervalSince1970: TimeInterval(jmessage.timestamp.intValue / 1000)))
//                let m = JCMessage(content: timeContent)
//                m.options.showsTips = false
//                self.messages.append(m)
//                chatView.append(m)
//            }
//            self.messages.append(message)
//            self.jmessages.append(msg)
//            chatView.append(message)
//            conversation.clearUnreadCount()
//            if !chatView.isRoll {
//                chatView.scrollToLast(animated: true)
//            }
//        }
//    }
    

    func onSendMessageResponse(_ message: JMSGMessage!, error: Error!) {
        printLog("")
        if let error = error as NSError? {
            if error.code == 803009 {
                MBProgressHUD_JChat.show(text: "发送失败，消息中包含敏感词", view: view, 2.0)
            }
            if error.code == 803005 {
                MBProgressHUD_JChat.show(text: "您已不是聊天室成员", view: view, 2.0)
            }
        }
        if let index = messages.index(message) {
            let msg = messages[index]
            msg.options.state = message.ex.state
            chatView.update(msg, at: index)
        }else {
            let jcMsg = _parseMessage(message,false)
            jmessages.append(message)
            messages.append(jcMsg)
            chatView.append(jcMsg)
        }
    }
    
    func onReceive(_ retractEvent: JMSGMessageRetractEvent!) {
        if let index = messages.index(retractEvent.retractMessage) {
            let msg = _parseMessage(retractEvent.retractMessage, false)
            messages[index] = msg
            chatView.update(msg, at: index)
        }
    }
    
    func onReceive(_ events: [JMSGChatRoomAdminChangeEvent]!) {//
        for event in events {
            let event: JMSGChatRoomAdminChangeEvent! = event
            var msgStr: String! = ""
            var nameStr: String! = ""
            for user in event.targetList{
                let user: JMSGUser! = user
                if(user.uid == JMSGUser.myInfo().uid){
                    nameStr = nameStr + "你"
                }else{
                    nameStr = nameStr + user.displayName()
                }
            }
            if event.eventType == JMSGEventNotificationType(rawValue: 130){
                msgStr = nameStr + "被设置成管理员"
            }else{
                msgStr = nameStr +  "被取消管理员"
            }
            let noticeContent = JCMessageNoticeContent(text: msgStr)
            let jcMsg = JCMessage.init(content: noticeContent)
            messages.append(jcMsg)
            chatView.append(jcMsg)
            if !chatView.isRoll {
                chatView.scrollToLast(animated: true)
            }
        }
    }
}

extension JCChatRoomChatViewController: AAPhotoBrowserProtocol {
    
    func numberOfPhotos(with browser: AAPhotoBrowser) -> Int {
        return jmessages.count
    }
    
    func photo(of index: Int, with browser: AAPhotoBrowser) -> AAPhoto {
        
        let jmsg = jmessages[index]
        
        let photo = AAPhoto(jmessage: jmsg, originalView: nil)
//        let photo = AAPhoto.init(urlString: String, placeholderImage: UIImage?, originalView: UIImageView?)
        return photo
        
    }
}

// MARK: - JCMessageDelegate
extension JCChatRoomChatViewController: JCMessageDelegate {
    
    // 播放视频
    func message(message: JCMessageType, videoData data: Data?) {
        if let data = data {
            JCVideoManager.playVideo(data: data, currentViewController: self)
        }
    }

    // 点击地址
    func message(message: JCMessageType, location address: String?, lat: Double, lon: Double) {
//        let vc = JCAddMapViewController()
//        vc.isOnlyShowMap = true
//        vc.lat = lat
//        vc.lon = lon
//        navigationController?.pushViewController(vc, animated: true)
    }

    // 点击图片
    func message(message: JCMessageType, image: UIImage?) {
//        debugPrint("\(String(describing: message.jmessage))")
//
//        let browserImageVC = JCImageBrowserViewController()
//        browserImageVC.messages = messages
//        browserImageVC.conversation = conversation
//        browserImageVC.currentMessage = message
//        present(browserImageVC, animated: true) {
//            self.toolbar.isHidden = true
//        }
        jmessages.removeAll()
                
        jmessages = getImageMessages(messages)
        if jmessages.count > 0 {
            var currentIndex = 0
            if let index = jmessages.index(where: { (m) -> Bool in
                m.msgId == message.msgId
            }) {
                currentIndex = index
            }
            
            let broswer = AAPhotoBrowser.init(with: self)
            broswer.selectedIndex = currentIndex
            broswer.presentDuration = 0.3
            broswer.dissmissDuration = 0.3
            present(broswer, animated: true) {
//                self.toolbar.isHidden = true
            }
        }
    }
    
    func getImageMessages(_ messages: [JCMessageType]) -> [JMSGMessage] {
        var imageMessages: [JMSGMessage] = []
        for message in messages {
            var msg: JMSGMessage?
            if message.targetType == .chatRoom {
                msg = message.jmessage
            }else{
                msg = conversation.message(withMessageId: message.msgId)
            }
            if msg != nil {
                if msg?.contentType == .image {
                    imageMessages.append(msg!)
                }
            }
        }
        return imageMessages
    }

    // 点击文件
    func message(message: JCMessageType, fileData data: Data?, fileName: String?, fileType: String?) {
        if data == nil {
            let vc = JCFileDownloadViewController()
            vc.title = fileName
            let msg = message.jmessage
            vc.fileSize = msg?.ex.fileSize
            vc.message = msg
            navigationController?.pushViewController(vc, animated: true)
        } else {
            guard let fileType = fileType else {
                return
            }
            let msg = conversation.message(withMessageId: message.msgId)!
            let content = msg.content as! JMSGFileContent
            switch fileType.fileFormat() {
            case .document:
                let vc = JCDocumentViewController()
                vc.title = fileName
                vc.fileData = data
                vc.filePath = content.originMediaLocalPath
                vc.fileType = fileType
                navigationController?.pushViewController(vc, animated: true)
            case .video, .voice:
                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
                try! JCVideoManager.playVideo(data: Data(contentsOf: url), fileType, currentViewController: self)
            case .photo:
                let browserImageVC = JCImageBrowserViewController()
                let image = UIImage(contentsOfFile: content.originMediaLocalPath ?? "")
                browserImageVC.imageArr = [image!]
                browserImageVC.imgCurrentIndex = 0
                present(browserImageVC, animated: true) {
                    self.toolbar.isHidden = true
                }
            default:
                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
                documentInteractionController.url = url
                documentInteractionController.presentOptionsMenu(from: .zero, in: self.view, animated: true)
            }
        }
    }

    // 点击名片
    func message(message: JCMessageType, user: JMSGUser?, businessCardName: String, businessCardAppKey: String) {
        if let user = user {
            let vc = JCUserInfoViewController()
            vc.user = user
            navigationController?.pushViewController(vc, animated: true)
        }
    }

    // 点击头像
    func tapAvatarView(message: JCMessageType) {
        //printLog("点击头像")
        toolbar.resignFirstResponder()
//        if message.options.alignment == .right {
//            navigationController?.pushViewController(JCMyInfoViewController(), animated: true)
//        } else {
//            let vc = JCUserInfoViewController()
//            vc.user = message.sender
//            navigationController?.pushViewController(vc, animated: true)
//        }
        let c = MineViewController(username: message.sender?.username)
        navigationController?.pushViewController(c, animated: true)
    }

    // 长按 @ 功能
//    func longTapAvatarView(message: JCMessageType) {
//        if !isGroup || message.options.alignment == .right {
//            return
//        }
//        toolbar.becomeFirstResponder()
//        if let user = message.sender {
//            toolbar.text.append("@")
//            handleAt(toolbar, NSMakeRange(toolbar.text.length - 1, 0), user, false, user.displayName().length)
//        }
//    }

    // 已读未读功能
//    func tapUnreadTips(message: JCMessageType) {
//        let vc = UnreadListViewController()
//        let msg = conversation.message(withMessageId: message.msgId)
//        vc.message = msg
//        navigationController?.pushViewController(vc, animated: true)
//    }
    
    func tapRedPack(message: JCMessageType) {
        //MBProgressHUD_JChat.show(text: "你点击了红包", view: self.view)
        if let dict = message.jmessage?.content?.extras, let redpackId: Int = dict["redpacketId"] as? Int {
            if let msgId = message.jmessage?.serverMessageId {
                MTRedpackTool.default.redpackInfo(self, redpacketId: redpackId, from: 2, msgId: msgId, type: MTRedpacketType.platform) { [weak self] in
                    guard let weakSelf = self else { return }
//                    if let index = weakSelf.messages.index(message) {
//                        let msg = weakSelf._parseMessage(weakSelf.conversation.message(withMessageId: message.msgId)!, false)
//                        weakSelf.messages[index] = msg
                        DispatchQueue.main.async {
                            weakSelf.chatView.reloadData()
                        }
//                    }
                }
            }
        }
    }
    
    func tapRedPackNotify(message: JCMessageType) {
        if let dict = message.jmessage?.content?.extras, let redpackId: Int = dict["id"] as? Int {
            if let msgId = message.jmessage?.serverMessageId {
                MTRedpackTool.default.redpackInfo(self, redpacketId: redpackId, from: 2, msgId: msgId, type: MTRedpacketType.platform) { [weak self] in
                    guard let weakSelf = self else { return }
//                    if let index = weakSelf.messages.index(message) {
//                        let msg = weakSelf._parseMessage(weakSelf.conversation.message(withMessageId: message.msgId)!, false)
//                        weakSelf.messages[index] = msg
                        DispatchQueue.main.async {
                            weakSelf.chatView.reloadData()
                        }
//                    }
                }
            }
        }
    }
}

// MARK: JCChatViewDelegate
extension JCChatRoomChatViewController: JCChatViewDelegate {
    func deleteMessage(message: JCMessageType) {
        printLog("删除")
        //conversation.deleteMessage(withMessageId: message.msgId)
        if let index = messages.index(message) {
            jMessageCount -= 1
            messages.remove(at: index)
            if let message = messages.last {
                if message.content is JCMessageTimeLineContent {
                    messages.removeLast()
                    chatView.remove(at: messages.count)
                }
            }
        }
    }


    // 撤回
    func withdrawMessage(message: JCMessageType) {
        printLog("消息撤回")
        guard let message = message.jmessage else {
            return
        }
        JMSGMessage.retractMessage(message, completionHandler: { (result, error) in
            if error == nil {
                if let index = self.messages.index(message) {
                    let msg = self._parseMessage(self.conversation.message(withMessageId: message.msgId)!, false)
                    self.messages[index] = msg
                    self.chatView.update(msg, at: index)
                }
            } else {
                MBProgressHUD_JChat.show(text: "发送时间过长，不能撤回", view: self.view)
            }
        })
    }

    func indexPathsForVisibleItems(chatView: JCChatView, items: [IndexPath]) {
        for item in items {
            if item.row <= minIndex {
                var msgs: [JCMessage] = []
                for index in item.row...minIndex  {
                    msgs.append(messages[index])
                }
//                updateUnread(msgs)
                minIndex = item.row
            }
        }
    }
}

// MARK: - SAIToolboxInputViewDataSource & SAIToolboxInputViewDelegate
extension JCChatRoomChatViewController: SAIToolboxInputViewDataSource, SAIToolboxInputViewDelegate {
    
    open func toolboxInputViewContentSize(_ inputView: UIView) -> CGSize {
        return CGSize(width: view.frame.width, height: 138)
    }
    
    open func numberOfToolboxItems(in toolbox: SAIToolboxInputView) -> Int {
        return _toolboxItems.count
    }
    open func toolbox(_ toolbox: SAIToolboxInputView, toolboxItemForItemAt index: Int) -> SAIToolboxItem {
        return _toolboxItems[index]
    }
    open func toolbox(_ toolbox: SAIToolboxInputView, numberOfRowsForSectionAt index: Int) -> Int {
        return 1
    }
    open func toolbox(_ toolbox: SAIToolboxInputView, numberOfColumnsForSectionAt index: Int) -> Int {
        return 4
    }
    open func toolbox(_ toolbox: SAIToolboxInputView, insetForSectionAt index: Int) -> UIEdgeInsets {
        return UIEdgeInsets.init(top: 12, left: 10, bottom: 12, right: 10)
    }
    open func toolbox(_ toolbox: SAIToolboxInputView, shouldSelectFor item: SAIToolboxItem) -> Bool {
        return true
    }
    private func _pushToSelectPhotos() {
        let vc = YHPhotoPickerViewController()
        vc.modalPresentationStyle = .fullScreen
        vc.maxPhotosCount = 9;
        vc.pickerDelegate = self
        present(vc, animated: true)
    }
    open func toolbox(_ toolbox: SAIToolboxInputView, didSelectFor item: SAIToolboxItem) {
        toolbar.resignFirstResponder()
        switch item.identifier {
        case "page:pic":
            if PHPhotoLibrary.authorizationStatus() != .authorized {
                PHPhotoLibrary.requestAuthorization({ (status) in
                    DispatchQueue.main.sync {
                        if status != .authorized {
                            JCAlertView.bulid().setTitle("无权限访问照片").setMessage("请在设备的设置-觅颜Me中允许访问照片。").setDelegate(self).addCancelButton("好的").addButton("去设置").setTag(10001).show()
                        } else {
                            self._pushToSelectPhotos()
                        }
                    }
                })
            } else {
                _pushToSelectPhotos()
            }
        case "page:camera":
            present(imagePicker, animated: true, completion: nil)
        case "page:redpack":
            debugPrint("红包")
            self.sendRedpack()
        default:
            break
        }
    }

//    open override func present(_ viewControllerToPresent: BaseViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
//        super.present(viewControllerToPresent, animated: flag, completion: completion)
//    }
}
// MARK: - SAIInputBarDelegate & SAIInputBarDisplayable
extension JCChatRoomChatViewController: SAIInputBarDelegate, SAIInputBarDisplayable {
    
    open override var inputAccessoryView: UIView? {
        return toolbar
    }
    open var scrollView: SAIInputBarScrollViewType {
        return chatView
    }
    open override var canBecomeFirstResponder: Bool {
        return true
    }

    open func inputView(with item: SAIInputItem) -> UIView? {
        if let view = inputViews[item.identifier] {
            return view
        }
        switch item.identifier {
        case "kb:emoticon":
            let view = JCEmoticonInputView()
            view.delegate = self
            view.dataSource = self
            inputViews[item.identifier] = view
            return view
        case "kb:toolbox":
            let view = SAIToolboxInputView()
            view.delegate = self
            view.dataSource = self
            inputViews[item.identifier] = view
            return view
        default:
            return nil
        }
    }

    open func inputViewContentSize(_ inputView: UIView) -> CGSize {
        return CGSize(width: view.frame.width, height: 216)
    }

    func inputBar(_ inputBar: SAIInputBar, shouldDeselectFor item: SAIInputItem) -> Bool {
        return true
    }
    open func inputBar(_ inputBar: SAIInputBar, shouldSelectFor item: SAIInputItem) -> Bool {
        if item.identifier == "kb:audio" {
            return true
        } else if item.identifier == "kb:emoticon" {
            if toolbar.hasUserInputText() == false {
                toolbar.setInputViewText("")
            }
            return true
        } else if item.identifier == "kb:toolbox" {
            if toolbar.hasUserInputText() == false {
                toolbar.setInputViewText(AppPlaceholder.inputViewPlaceholder)
            }
            return true
        }
        guard let _ = inputView(with: item) else {
            return false
        }
        return true
    }
    open func inputBar(_ inputBar: SAIInputBar, didSelectFor item: SAIInputItem) {
        inputItem = item

        if item.identifier == "kb:audio" {
            inputBar.deselectBarAllItem()
            return
        } else if item.identifier == "kb:emoticon" {
            if toolbar.hasUserInputText() == false {
                toolbar.setInputViewText("")
            }
        }
        if let kb = inputView(with: item) {
            inputBar.setInputMode(.selecting(kb), animated: true)
        }
    }
    open func inputBar(didChangeMode inputBar: SAIInputBar) {
        if inputItem?.identifier == "kb:audio" {
            return
        } else if inputItem?.identifier == "kb:emoticon" {
            if toolbar.hasUserInputText() == false {
                toolbar.setInputViewText("")
            }
        }
        if let item = inputItem, !inputBar.inputMode.isSelecting {
            inputBar.deselectBarItem(item, animated: true)
        }
    }

    open func inputBar(didChangeText inputBar: SAIInputBar) {
        _emoticonSendBtn.isEnabled = inputBar.attributedText.length != 0
    }

    public func inputBar(shouldReturn inputBar: SAIInputBar) -> Bool {
        printLog("input bar should return")
        if inputBar.attributedText.length == 0 {
            return false
        }
        send(forText: inputBar.attributedText)
        inputBar.attributedText = nil
        return false
    }

//
    func inputBar(touchDown recordButton: UIButton, inputBar: SAIInputBar) {
        if recordingHub != nil {
            recordingHub.removeFromSuperview()
        }
        recordingHub = JCRecordingView(frame: CGRect.zero)
        recordHelper.updateMeterDelegate = recordingHub
        recordingHub.startRecordingHUDAtView(view)
        recordingHub.frame = CGRect(x: view.centerX - 70, y: view.centerY - 70, width: 136, height: 136)
        recordHelper.startRecordingWithPath(String.getRecorderPath()) {
        }
    }

    func inputBar(dragInside recordButton: UIButton, inputBar: SAIInputBar) {
        recordingHub.pauseRecord()
    }

    func inputBar(dragOutside recordButton: UIButton, inputBar: SAIInputBar) {
        recordingHub.resaueRecord()
    }

    func inputBar(touchUpInside recordButton: UIButton, inputBar: SAIInputBar) {
        printLog("record voice")
        if recordHelper.recorder ==  nil {
            return
        }
        recordHelper.finishRecordingCompletion()
        if (recordHelper.recordDuration! as NSString).floatValue < 1 {
            recordingHub.showErrorTips()
            let time: TimeInterval = 1.5
            let hub = recordingHub
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
                hub?.removeFromSuperview()
            }
            return
        } else {
            recordingHub.removeFromSuperview()
        }
        let data = try! Data(contentsOf: URL(fileURLWithPath: recordHelper.recordPath!))
        send(voiceData: data, duration: Double(recordHelper.recordDuration!)!)
    }

    func inputBar(touchUpOutside recordButton: UIButton, inputBar: SAIInputBar) {
        recordHelper.cancelledDeleteWithCompletion()
        recordingHub.removeFromSuperview()
    }
}

// MARK: - JCEmoticonInputViewDataSource & JCEmoticonInputViewDelegate
extension JCChatRoomChatViewController: JCEmoticonInputViewDataSource, JCEmoticonInputViewDelegate {
    
    open func numberOfEmotionGroups(in emoticon: JCEmoticonInputView) -> Int {
        return _emoticonGroups.count
    }

    open func emoticon(_ emoticon: JCEmoticonInputView, emotionGroupForItemAt index: Int) -> JCEmoticonGroup {
        return _emoticonGroups[index]
    }

    open func emoticon(_ emoticon: JCEmoticonInputView, numberOfRowsForGroupAt index: Int) -> Int {
        return _emoticonGroups[index].rows
    }

    open func emoticon(_ emoticon: JCEmoticonInputView, numberOfColumnsForGroupAt index: Int) -> Int {
        return _emoticonGroups[index].columns
    }

    open func emoticon(_ emoticon: JCEmoticonInputView, moreViewForGroupAt index: Int) -> UIView? {
        if _emoticonGroups[index].type.isSmall {
            return _emoticonSendBtn
        } else {
            return nil
        }
    }

    open func emoticon(_ emoticon: JCEmoticonInputView, insetForGroupAt index: Int) -> UIEdgeInsets {
        return UIEdgeInsets.init(top: 12, left: 10, bottom: 12 + 24, right: 10)
    }

    open func emoticon(_ emoticon: JCEmoticonInputView, didSelectFor item: JCEmoticon) {
        if item.isBackspace {
            toolbar.deleteBackward()
            return
        }
        if let emoticon = item as? JCCEmoticonLarge {
            send(forLargeEmoticon: emoticon)
            return
        }
        if let code = item.contents as? String {
            return toolbar.insertText(code)
        }
        if let image = item.contents as? UIImage {
            let d = toolbar.font?.descender ?? 0
            let h = toolbar.font?.lineHeight ?? 0
            let attachment = NSTextAttachment()
            attachment.image = image
            attachment.bounds = CGRect(x: 0, y: d, width: h, height: h)
            toolbar.insertAttributedText(NSAttributedString(attachment: attachment))
            return
        }
    }
}

// MARK: - UIImagePickerControllerDelegate & YHPhotoPickerViewControllerDelegate
extension JCChatRoomChatViewController: YHPhotoPickerViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    func selectedPhotoBeyondLimit(_ count: Int32, currentView view: UIView!) {
        MBProgressHUD_JChat.show(text: "最多选择\(count)张图片", view: nil)
    }
    
    func yhPhotoPickerViewController(_ PhotoPickerViewController: YHSelectPhotoViewController!, selectedPhotos photos: [Any]!) {
        for item in photos {
            guard let photo = item as? UIImage else {
                return
            }
            DispatchQueue.main.async {
                self.send(forImage: photo)
            }
        }
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        // Local variable inserted by Swift 4.2 migrator.
        let infoE = convertFromUIImagePickerControllerInfoKeyDictionary(info)
        
        picker.dismiss(animated: true, completion: nil)
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            send(forImage: image.fixOrientation())
        } else {
            loadImageFromPicker(info: info)
        }
        
        let videoUrl = infoE[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.mediaURL)] as! URL?
        if videoUrl != nil {
            let format = "mov" //系统拍的是 mov 格式
            let videoData = try! Data(contentsOf: videoUrl!)
            let thumb = self.videoFirstFrame(videoUrl!, size: CGSize(width: JC_VIDEO_MSG_IMAGE_WIDTH, height: JC_VIDEO_MSG_IMAGE_HEIGHT));
            let thumbData = thumb.pngData()
            let avUrl = AVURLAsset(url: videoUrl!)
            let time = avUrl.duration
            let seconds = ceil(Double(time.value)/Double(time.timescale))
            self.send(videoData: videoData, thumbData: thumbData!, duration: seconds, format: format)
            
            /* 可选择转为 MP4 再发
             conversionVideoFormat(videoUrl!) { (paraUrl) in
             if paraUrl != nil {
             //send  video message
             }
             }*/
        }
    }
    
    private func loadImageFromPicker(info: [UIImagePickerController.InfoKey : Any]) {
        guard let referenceURL = info[UIImagePickerController.InfoKey.phAsset] as? URL else {
            return
        }
        let fetchResult = PHAsset.fetchAssets(withALAssetURLs: [referenceURL], options: nil)
        guard let phAsset = fetchResult.firstObject else {
            return
        }
        // size doesn't matter, because resizeMode = .none
        let size = CGSize(width: 32, height: 32)
        let options = PHImageRequestOptions()
        options.version = .original
        options.deliveryMode = .highQualityFormat
        options.resizeMode = .none
        options.isNetworkAccessAllowed = true
        PHImageManager.default().requestImage(for: phAsset, targetSize: size, contentMode: .aspectFit, options: options) { [weak self] (image, info) in
            if let weakSelf = self, let image = image {
                DispatchQueue.main.async {
                    weakSelf.send(forImage: image.fixOrientation())
                }
            }
        }
    }
    
    // 视频转 MP4 格式
    func conversionVideoFormat(_ inputUrl: URL,callback: @escaping (_ para: URL?) -> Void){
        let date = Date()
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd-HH:mm:ss"
        let strDate = formatter.string(from: date) as String
        
        let path = "\(NSHomeDirectory())/Documents/output-\(strDate).mp4"
        let outputUrl: URL = URL(fileURLWithPath: path)
        
        let avAsset = AVURLAsset(url: inputUrl)
        let exportSeesion = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetMediumQuality)
        exportSeesion?.outputURL = outputUrl
        exportSeesion?.outputFileType = AVFileType.mp4
        exportSeesion?.exportAsynchronously(completionHandler: {
            switch exportSeesion?.status {
            case AVAssetExportSession.Status.unknown?:
                break;
            case AVAssetExportSession.Status.cancelled?:
                callback(nil)
                break;
            case AVAssetExportSession.Status.waiting?:
                break;
            case AVAssetExportSession.Status.exporting?:
                break;
            case AVAssetExportSession.Status.completed?:
                callback(outputUrl)
                break;
            case AVAssetExportSession.Status.failed?:
                callback(nil)
                break;
            default:
                callback(nil)
                break
            }
        })
    }
    // 获取视频第一帧
    func videoFirstFrame(_ videoUrl: URL, size: CGSize) -> UIImage {
        let opts = [AVURLAssetPreferPreciseDurationAndTimingKey:false]
        let urlAsset = AVURLAsset(url: videoUrl, options: opts)
        let generator = AVAssetImageGenerator(asset: urlAsset)
        generator.appliesPreferredTrackTransform = true
        generator.maximumSize = CGSize(width: size.width, height: size.height)
        //let error: Error
        do {
            let img = try generator.copyCGImage(at: CMTimeMake(value: 0, timescale: 10), actualTime: nil) as CGImage
            let image = UIImage(cgImage: img)
            return image
        } catch let error as NSError {
            debugPrint("\(error)")
            return UIImage.createImage(color: .gray, size: CGSize(width: JC_VIDEO_MSG_IMAGE_WIDTH, height: JC_VIDEO_MSG_IMAGE_HEIGHT))!
        }
    }
}

// MARK: UIAlertViewDelegate

extension JCChatRoomChatViewController: UIAlertViewDelegate {
    
    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
        if alertView.tag == 10001 {
            if buttonIndex == 1 {
                JCAppManager.openAppSetter()
            }
            return
        }
        /*
        switch buttonIndex {
        case 1:
            if let index = messages.index(currentMessage) {
                messages.remove(at: index)
                chatView.remove(at: index)
                let msg = conversation.message(withMessageId: currentMessage.msgId)
                currentMessage.options.state = .sending
                
                if let msg = msg {
                    if let content = currentMessage.content as? JCMessageImageContent,
                        let imageContent = msg.content as? JMSGImageContent
                    {
                        imageContent.uploadHandler = {  (percent:Float, msgId:(String?)) -> Void in
                            content.upload?(percent)
                        }
                    }
                }
                messages.append(currentMessage as! JCMessage)
                chatView.append(currentMessage)
                conversation.send(msg!, optionalContent: JMSGOptionalContent.ex.default)
                chatView.scrollToLast(animated: true)
            }
        default:
            break
        }
        */
    }
}

// MARK: - JCRecordVoiceHelperDelegate
extension JCChatRoomChatViewController: JCRecordVoiceHelperDelegate {
    public func beyondLimit(_ time: TimeInterval) {
        recordHelper.finishRecordingCompletion()
        recordingHub.removeFromSuperview()
        let data = try! Data(contentsOf: URL(fileURLWithPath: recordHelper.recordPath!))
        send(voiceData: data, duration: Double(recordHelper.recordDuration!)!)
    }
}

// MARK: UIGestureRecognizerDelegate

extension JCChatRoomChatViewController: UIGestureRecognizerDelegate {
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        guard let view = touch.view else {
            return true
        }
        if view.isKind(of: JCMessageTextContentView.self) {
            return false
        }
        return true
    }
}

extension JCChatRoomChatViewController {
    
    override func yp_navigtionBarConfiguration() -> YPNavigationBarConfigurations {
        return [.backgroundStyleColor, .backgroundStyleOpaque, .showShadowImage]
    }
}


// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromUIImagePickerControllerInfoKeyDictionary(_ input: [UIImagePickerController.InfoKey: Any]) -> [String: Any] {
    return Dictionary(uniqueKeysWithValues: input.map {key, value in (key.rawValue, value)})
}

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromUIImagePickerControllerInfoKey(_ input: UIImagePickerController.InfoKey) -> String {
    return input.rawValue
}
